﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Aspose.Cells;
using Dm;
using Mapster.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using NPOI.SS.Formula.Functions;
using SHZY.BaseData.Entitys.Common.Entity;
using SHZY.Business.Entity.Common;
using SHZY.Business.Entitys.Common.Dto.PrintExecute;
using SHZY.Business.Entitys.Common.Entity;
using SHZY.Business.Entitys.WMS.Entity;
using SHZY.Business.Interfaces.Common;
using SHZY.Common.Core.Manager;
using SHZY.Common.Core.Manager.Files;
using SHZY.Common.Enum;
using SHZY.Common.Extension;
using SHZY.Common.FR;
using SHZY.Common.Security;
using SHZY.DependencyInjection;
using SHZY.DynamicApiController;
using SHZY.FriendlyException;
using SHZY.Systems.Entitys.Model.PrintDev;
using SHZY.Systems.Interfaces.System;
using SqlSugar;

namespace SHZY.Business.Common
{
    /// <summary>
    /// 业务实现：打印执行.
    /// </summary>
    [ApiDescriptionSettings(Tag = "Business", Name = "PrintExecute", Order = 200)]
    [Route("api/Common/Business/[controller]")]
    public class ComBasePrintExecuteService : IComBasePrintExecuteService, IDynamicApiController, ITransient
    {
        /// <summary>
        /// 数据业务仓储.
        /// </summary>
        private readonly ISqlSugarRepository<ComBasePrintConfigEntity> _repository;

        /// <summary>
        /// 数据接口服务.
        /// </summary>
        private readonly IDataInterfaceService _dataInterfaceService;

        /// <summary>
        /// 用户管理.
        /// </summary>
        private readonly IUserManager _userManager;

        /// <summary>
        /// 多租户事务.
        /// </summary>
        private readonly ITenant _db;

        /// <summary>
        /// 文件服务.
        /// </summary>
        private readonly IFileManager _fileManager;

        /// <summary>
        /// 数据连接服务.
        /// </summary>
        private readonly IDbLinkService _dbLinkService;

        /// <summary>
        /// 数据库管理.
        /// </summary>
        private readonly IDataBaseManager _dataBaseManager;

        /// <summary>
        /// 缓存管理.
        /// </summary>
        private readonly ICacheManager _cacheManager;

        /// <summary>
        /// 初始化一个<see cref="ComBasePrintExecuteService"/>类型的新实例.
        /// </summary>
        public ComBasePrintExecuteService(ISqlSugarRepository<ComBasePrintConfigEntity> comBasePrintExecuteRepository,
            IDataInterfaceService dataInterfaceService,
        ISqlSugarClient context,
        IUserManager userManager,
        IFileManager fileManager,
        IDbLinkService dbLinkService,
        IDataBaseManager dataBaseManager,
        ICacheManager cacheManager)
        {
            _repository = comBasePrintExecuteRepository;
            _dataInterfaceService = dataInterfaceService;
            _userManager = userManager;
            _dbLinkService = dbLinkService;
            _dataBaseManager = dataBaseManager;
            _fileManager = fileManager;
            _cacheManager = cacheManager;
            _db = context.AsTenant();
        }

        /// <summary>
        /// 打印预览.
        /// </summary>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPost("fastreportpreview")]
        public async Task<dynamic> GetPreview([FromBody] ComBasePrintExecuteCrInput input)
        {
            if (input.printQty.IsNullOrEmpty() || input.printQty <= 0)
                throw Oops.Bah("打印数量不能小于1");

            input.printQty = 1;  // 预览默认打印数量为1
            var ms = await PrintLabelExeture(input, FastReportExportType.Image, false);
            return ms;
        }

        /// <summary>
        /// 打印生成PDF.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("fastreportprint")]
        public async Task<dynamic> PrintExportPDF([FromBody] ComBasePrintExecuteCrInput input)
        {
            if (input.printQty.IsNullOrEmpty() || input.printQty <= 0)
                throw Oops.Bah("打印数量不能小于1");
            return await PrintLabelExeture(input, FastReportExportType.PDF, true);
        }

        /// <summary>
        /// ZPL指令发送打印机.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("fastreportzplprint")]
        public async Task<dynamic> PrintExeportZpl([FromBody] ComBasePrintExecuteCrInput input)
        {
            if (input.printQty.IsNullOrEmpty() || input.printQty <= 0)
                throw Oops.Oh("打印数量不能小于1");
            if (string.IsNullOrEmpty(input.printerIp))
                throw Oops.Oh("请选择打印机");
            return await PrintLabelExeture(input, FastReportExportType.ZPL, true);

        }

        /// <summary>
        /// MAC指令发送打印机.
        /// </summary>
        /// <param name="Unpack"></param>
        /// <returns></returns>
        [HttpPost("fastreportunpackingprint")]
        public async Task<dynamic> PrintUnpackingExeport([FromBody] PrintUnpackingExecuteInput Unpack)
        {
            if (!string.IsNullOrEmpty(Unpack.printerIp))
            {
                var config = await _repository.Context.Queryable<ComBasePrinterConfigEntity>().Where(x => x.ComputerIp.Contains(Unpack.printerIp) && x.DeleteMark == null && x.EnabledMark == 1).FirstAsync();
                if (config == null)
                {
                    throw Oops.Oh("未找到对应IP地址");
                }

                ComBasePrintExecuteCrInput input = new ComBasePrintExecuteCrInput();

                //查询拆包打印配置
                var baseEvent = await _repository.Context.Queryable<ComBaseEventEntity>().Where(x => x.EventCode == Unpack.eventCode).OrderBy(x => x.CreatorTime, OrderByType.Desc).FirstAsync();
                if (baseEvent != null)
                {
                    input.printConfigId = baseEvent.PrintConfigId;
                }

                input.formDataId = Unpack.formDataId;
                input.formCustomerId = Unpack.formCustomerId;
                input.printQty = Unpack.printQty;
                input.packageQty = Unpack.packageQty;
                input.formQty = Unpack.formQty;
                input.printerIp = config.PrinterIp;
                return await PrintLabelExeture(input, FastReportExportType.ZPL, true);
            }
            else
            {
                throw Oops.Oh("请选择打印机");
            }
        }

        #region PublicMethod

        /// <summary>
        /// 标签打印执行函数.
        /// </summary>
        /// <param name="input">输入参数.</param>
        /// <param name="exportType">导出类型.</param>
        /// <param name="IsSaveLog">是否保存打印记录.</param>
        /// <returns></returns>
        [NonAction]
        public async Task<FileResult> PrintLabelExeture(ComBasePrintExecuteCrInput input, FastReportExportType exportType, bool IsSaveLog)
        {
            // 查询打印配置 获取打印模板文件和数据源SQL
            var printConfigData = await _repository.Context.Queryable<ComBasePrintConfigEntity>()
                .LeftJoin<ComBasePrintTemplateEntity>((x, a) => x.PrintTemplateId == a.Id && a.DeleteMark == null)
                .LeftJoin<ComBasePrintDataEntity>((x, a, b) => x.DataSourceId == b.Id && b.DeleteMark == null)
                .Where(x => x.Id == input.printConfigId)
                .Select((x, a, b) => new
                {
                    PrintTemplateId = x.PrintTemplateId,
                    TemplateFileInfo = a.FileInfo,
                    IsCustomer = x.IsCustomer,
                    dbLinkId = b.DbLinkId,
                    dataSql = b.SqlTemplate,
                    labelRuler = x.LabelRulerTemplate
                }).FirstAsync();

            if (printConfigData == null)
                throw Oops.Bah("未查找到相关打印配置!");

            #region 查找打印模板文件路径

            string fileInfoJson = printConfigData.TemplateFileInfo.ToString();
            // 判断是否匹配客户模板
            if (printConfigData.IsCustomer == 1)
            {
                var customerFile = await _repository.Context.Queryable<ComBasePrintTemplateCustomerEntity>()
                    .Where(x => x.CustomerId == input.formCustomerId && x.DeleteMark == null)
                    .Select(s => s.FileInfo).FirstAsync();

                fileInfoJson = customerFile.ToString();
            }

            // 获取模板文件名
            string filename = fileInfoJson.ToList<FileInfoModel>()[0].fileId;
            string filePath = Path.Combine(GetPathByType("annex"), filename);

            #endregion

            #region 查找数据源

            var link = await _dbLinkService.GetInfo(printConfigData.dbLinkId);
            var tenantLink = link ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName);

            var parameter = new List<SugarParameter>()
            {
               new SugarParameter("@formId", input.formDataId)
            };
            //var sqlList = printConfigData.dataSql.ToList<PrintDevSqlModel>();
            var sqlList = JsonHelper.ToObject<PrintDevSqlModel>(printConfigData.dataSql);

            if (sqlList.sql.IsNullOrEmpty())
                throw Oops.Bah("未设置数据源!");
            var dataTable = _dataBaseManager.GetInterFaceData(tenantLink, sqlList.sql, parameter.ToArray());
            if (dataTable == null || dataTable.Rows.Count == 0)
                throw Oops.Bah("未获取到打印数据!");

            //添加固定变量包装数量字段
            dataTable.Columns.Add("Qty");
            dataTable.Rows[0]["Qty"] = input.packageQty.ToString();
            #endregion
            #region 查找执行标签规则
            var dic = new Dictionary<string, ComBaseLabelRulesEntity>();
            var printSerialList = new List<ComBasePrintSerialEntity>();
            var lastSerialDic = new Dictionary<string, string>();
            // 定义打印序列号缓存key.
            string _cacheSerialKey = string.Format("PrintSerial{0}_{1}_{2}", _userManager.TenantId, printConfigData.PrintTemplateId, input.formDataId);
            if (!string.IsNullOrEmpty(printConfigData.labelRuler))
            {
                var labelList = printConfigData.labelRuler.ToList<LabelModel>();
                if (labelList != null && labelList.Count > 0)
                {
                    // 先根据打印模板，业务id 查询历史存储的序列号
                    printSerialList = await _repository.Context.Queryable<ComBasePrintSerialEntity>()
                       .Where(x => x.BusinessId == input.formDataId && x.PrintCode == printConfigData.PrintTemplateId).ToListAsync();

                    var rulerIdArry = labelList.Select(x => x.rulerId).ToList();
                    // 根据标签规则Id查出规则信息
                    var rulerInfoList = await _repository.Context.Queryable<ComBaseLabelRulesEntity>()
                        .Where(x => rulerIdArry.Contains(x.Id) && x.DeleteMark == null && x.EnabledMark == 1).ToListAsync();

                    labelList.ForEach(u => dic.Add(u.labefield, rulerInfoList.Where(x => x.Id == u.rulerId).First()));
                    // 初始执行时，默认取历史记录的序列号
                    // lastSerialDic = new Dictionary<string, string>();
                    if (printSerialList != null && printSerialList.Count > 0 && lastSerialDic.Count == 0)
                    {
                        printSerialList.ForEach(u => lastSerialDic.Add(u.LabelCode, u.SerialValue));
                    }
                }
            }
            #endregion
            #region 整合数据
            Dictionary<string, DataTable> dicList = new Dictionary<string, DataTable>();
            DataTable dt = dataTable.Clone();
            // 记录打印的序列号
            List<string> pSerialNo = new List<string>();
            // 根据打印次数，循环执行打印数据.
            for (int i = 0; i < input.printQty; i++)
            {
                // 判断最后存在尾箱。取余数作为最后一个尾箱标签
                if (input.formQty % input.packageQty != 0 && i == input.printQty - 1)
                    dataTable.Rows[0]["Qty"] = (input.formQty % input.packageQty).ToString();
                dt.Rows.Add(dataTable.Rows[0].ItemArray);

                if (!string.IsNullOrEmpty(printConfigData.labelRuler))
                {
                    // 循环标签变量，执行具体规则，获取最终变量值.
                    foreach (var item in dic.Keys)
                    {
                        if (_cacheManager.Exists(_cacheSerialKey))
                        {
                            lastSerialDic.Clear();
                            // 查询缓存序列号
                            lastSerialDic = await _cacheManager.GetAsync<Dictionary<string, string>>(_cacheSerialKey);
                        }
                        // 执行标签规则，获取变量名对应的值
                        string _resValue = LabelRulerExecute(printSerialList, item, dic[item], DateTime.Now, lastSerialDic);

                        // 添加变量字段及值到dataTabele中
                        if (!dt.Columns.Contains(item))
                            dt.Columns.Add(item);
                        dt.Rows[i][item] = _resValue;

                        // 判断是否为序列类型
                        if (dic[item].Type.Equals("2")) 
                        {
                            if (lastSerialDic.ContainsKey(item))
                            {

                                lastSerialDic[item] = _resValue;
                            }
                            else
                            {
                                lastSerialDic.Add(item, _resValue);
                            }

                            if(IsSaveLog) // 排除预览情况生成的序列号，不纳入缓存中
                                _cacheManager.Set(_cacheSerialKey, lastSerialDic, new TimeSpan(0, 3, 0));

                            ///////  注意 此处存储的序列号仅限于当前打印配置里只维护一个序列号规则的情况 ///////////////
                            pSerialNo.Add(_resValue);
                        }
                    }
                }
            }
            #endregion
            dicList.Add("PrintData", dt);
            FileResult ms = CreateFR.ExportLabelFastReport(filePath, dicList, exportType);

            #region 保存打印记录

            // 打印执行成功后 存储打印记录
            if (ms != null && IsSaveLog) 
            {
                List<ComBasePrintSerialEntity> psList = new List<ComBasePrintSerialEntity>();
                List<ComBasePrintLogEntity> plogList = new List<ComBasePrintLogEntity>();
                // 保存最近一次序号信息
                foreach (var item in lastSerialDic.Keys)
                {
                    if (printSerialList != null && printSerialList.Count > 0)
                    {
                        var _m = printSerialList.Where(x => x.LabelCode == item).First();
                        _m.SerialValue = lastSerialDic[item];
                        _m.SequenceTime = DateTime.Now;
                        psList.Add(_m);
                    }
                    else
                    {
                        psList.Add(new ComBasePrintSerialEntity()
                        {
                            BusinessId = input.formDataId,
                            PrintCode = printConfigData.PrintTemplateId,
                            LabelCode = item,
                            SerialValue = lastSerialDic[item],
                            SequenceTime = DateTime.Now,
                        });
                    }
                }

                var _log = new ComBasePrintLogEntity()
                {
                    CustomerId = input.formDataId,
                    IsRead = 0,
                    PrintFile = printConfigData.TemplateFileInfo.ToString(),
                    PrintNum = input.printQty,
                    PrintSerial = JsonHelper.ToJsonString(pSerialNo), // 将序列集合转存为json
                };

                try
                {
                    if (psList.Count > 0)
                    {
                        // 新增或修改序列号记录
                        _repository.Ado.BeginTran();
                        var x = await _repository.Context.Storageable(psList)
                            .WhereColumns(w => new { w.PrintCode, w.BusinessId, w.LabelCode }).ToStorageAsync();
                        // 执行插入方法
                        if (x.InsertList.Any())
                        {
                            await x.AsInsertable.CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
                        }
                        if (x.UpdateList.Any())
                        {
                            await x.AsUpdateable.CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync();
                        }

                    }

                    // 保存打印记录
                    await _repository.Context.Insertable(_log).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();

                    _repository.Ado.CommitTran();
                }
                catch (Exception)
                {
                    _repository.Ado.RollbackTran();
                }
            }
            #endregion

            // ZPL打印.
            if (exportType == FastReportExportType.ZPL)
            {
                FileStreamResult fileStream = ms as FileStreamResult;
                // 异步发送zpl文件流到指定打印机
                await Task.Run(() =>
                {
                    PrintZplExample(input.printerIp, fileStream.FileStream);
                });
                return null;
            }

            return ms;

        }

        /// <summary>
        /// 根据类型获取文件存储路径.
        /// </summary>
        /// <param name="type">文件类型.</param>
        /// <returns></returns>
        [NonAction]
        public string GetPathByType(string type)
        {
            return _fileManager.GetPathByType(type);
        }

        /// <summary>
        /// 使用PrintDocument类发送ZPL指令到打印机.
        /// </summary>
        /// <param name="printerName"></param>
        /// <param name="fileStream"></param>
        [NonAction]
        public void DocumentPrint(string printerName, Stream fileStream)
        { 
            PrintDocument pd = new PrintDocument();
            // 设置打印机
            pd.PrinterSettings.PrinterName = printerName;
            pd.PrintPage += (sender, e) =>
            {
                using (StreamReader sr = new StreamReader(fileStream))
                {
                    string zplContent = sr.ReadToEnd();
                    e.Graphics.DrawString(zplContent, new System.Drawing.Font("Arial", 10), Brushes.Black, 0, 0);
                }
            };
            pd.Print();
        }

        /// <summary>
        /// 使用TCP发送ZPL指令到打印机.
        /// </summary>
        /// <param name="printerIp"></param>
        /// <param name="fileStream"></param>
        [NonAction]
        public void PrintZplExample(string printerIp, Stream fileStream)
        {
            using (TcpClient client = new TcpClient(printerIp,9100))
            {
                using (StreamReader sr = new StreamReader(fileStream))
                {
                    using (StreamWriter writer = new StreamWriter(client.GetStream()))
                    {
                        writer.WriteAsync(sr.ReadToEnd());
                        writer.Flush();
                    }
                }
            }
        }

        #endregion

        #region PrivateMethod

        /// <summary>
        /// 执行标签规则.
        /// </summary>
        /// <param name="serialHistoryList">上次生成的序列号记录.</param>
        /// <param name="labelFeild">变量名.</param>
        /// <param name="labelRulesEntity">标签规则.</param>
        /// <param name="datetime">当前时间</param>
        /// <param name="dicLastField">缓存的上次变量对应标签规则执行结果.</param>
        /// <returns></returns>
        private string LabelRulerExecute(List<ComBasePrintSerialEntity> serialHistoryList,
            string labelFeild, ComBaseLabelRulesEntity labelRulesEntity, DateTime datetime, Dictionary<string, string> dicLastField)
        {
            var valueRes = "";
            // 判断标签规则是日期类型.
            if (labelRulesEntity.Type.Equals("1"))
            {
                valueRes = LabelDateFormat(labelRulesEntity.DateFormat, datetime);
            }
            else if (labelRulesEntity.Type.Equals("2"))  
            {
                // 判断标签规则是序列号
                var serialNo = labelRulesEntity.ResetValue; // 默认序列号初始值
                // 判断若存在上一个序列号，则取上一个序列号
                if (dicLastField != null && dicLastField.ContainsKey(labelFeild))
                    serialNo = dicLastField[labelFeild];

                // 判断序列号重置.
                if (serialHistoryList != null && serialHistoryList.Count > 0)
                {
                    var history = serialHistoryList.Where(x => x.LabelCode == labelFeild).First();
                    if (history != null)
                    {
                        var nowDate = DateTime.Now;
                        bool isReset = false;
                        // 判断重置时间
                        if (labelRulesEntity.ResetTime.Equals("2"))
                        {
                            // 按日重置
                            var resetDate = Convert.ToDateTime(history.SequenceTime).AddDays(1).Day;

                            if (resetDate <= nowDate.Day && !serialNo.Equals(history.SerialValue))
                                isReset = true;
                        }
                        else if (labelRulesEntity.ResetTime.Equals("3"))
                        {
                            // 按月重置
                            var resetDate = Convert.ToDateTime(history.SequenceTime).AddMonths(1).Month;
                            if (resetDate <= nowDate.Month && !serialNo.Equals(history.SerialValue))
                                isReset = true;

                        }
                        else if (labelRulesEntity.ResetTime.Equals("4"))
                        {
                            // 按年重置
                            var resetDate = Convert.ToDateTime(history.SequenceTime).AddYears(1).Year;
                            if (resetDate <= nowDate.Year && !serialNo.Equals(history.SerialValue))
                                isReset = true;

                        }
                        else if (serialNo.Equals(labelRulesEntity.SpecifiedValue) ||
                            serialNo.Equals(labelRulesEntity.MaxValue))
                        {
                            // 达到指定值或等于设定的最大值 重置
                            isReset = true;

                        }
                        if (isReset)
                        {
                            serialNo = labelRulesEntity.ResetValue;
                            // 重置序列号，恢复初始值
                            //updateSerial = new ComBasePrintSerialEntity()
                            //{
                            //    Id = history.Id, // id
                            //    PrintCode = history.PrintCode, // 打印模板id
                            //    BusinessId = history.BusinessId, // 打印业务数据Id
                            //    LabelCode = history.LabelCode,  // 标签变量
                            //    SerialValue = serialNo,  // 初始序列号
                            //    SequenceTime = DateTime.Now,
                            //};
                        }

                    }
                }
                valueRes = SerialMethod(labelRulesEntity.StepValue.ToString(), labelRulesEntity.Sequence, serialNo);
            }

            return valueRes;
        }

        /// <summary>
        /// 日期格式实现.
        /// </summary>
        /// <param name="labelFormat">日期格式.</param>
        /// <param name="time">日期.</param>
        /// <returns>value.</returns>
        private string LabelDateFormat(string labelFormat, DateTime time)
        {
            var _res = "";
            switch (labelFormat)
            {
                case "1":
                    _res = time.ToString("yyyy-MM-dd");
                    break;
                case "2":
                    _res = time.ToString("ddMMyyyy");
                    break;
                case "3":
                    _res = time.ToString("MMddyyyy");
                    break;
                case "4":
                    _res = time.ToString("HH:mm:ss");
                    break;
                case "5":
                    _res = time.ToString("HHmmss");
                    break;
                case "6":
                    _res = time.ToString("yy");
                    break;
                case "7":
                    _res = time.ToString("yyyy");
                    break;
                case "8":
                    _res = time.ToString("MM");
                    break;
                case "9":
                    _res = time.Month.ToString();
                    break;
                case "10":
                    _res = time.ToString("dd");
                    break;
                case "11":
                    _res = time.ToString("yy") + time.ToString("MM") + time.ToString("dd");
                    break;
                case "12":
                    _res = time.ToString("yyyy") + time.ToString("MM") + time.ToString("dd");
                    break;
                case "13":
                    _res = time.ToString("yyyy/MM/dd");
                    break;
                default:
                    break;
            }

            return _res;

        }

        /// <summary>
        /// 获取新组合的序列号.
        /// </summary>
        /// <param name="stepValue">步进值</param>
        /// <param name="Sequence">序列值循环范围</param>
        /// <param name="serialValue">序列号值</param>
        /// <returns></returns>
        private string SerialMethod(string stepValue, string Sequence, string serialValue)
        {
            var seqStr = Sequence.Split(',');
            if (seqStr.Length > 1)
            {
                // 加 "," 说明为数字，字母按序列号尾数(若是字母则A-Z循环，若是数字则0-9循环)
                var numCharArry = seqStr[0].ToArray();
                var LetterCharArry = seqStr[1].ToArray();

                if (string.Concat<char>(numCharArry).IndexOf(serialValue[serialValue.Length - 1]) > -1)
                {
                    return SerialCharMethod(stepValue, Sequence, serialValue, numCharArry);
                }
                else if (string.Concat<char>(LetterCharArry).IndexOf(serialValue[serialValue.Length - 1]) > -1)
                {
                    return SerialCharMethod(stepValue, Sequence, serialValue, LetterCharArry);

                }
                else
                {
                    string vOtherStr = SerialMethod(stepValue, Sequence, serialValue);
                    return vOtherStr;
                }

            }
            else
            {

                // 纯数字或字母或数字+字母组合循环
                var _arry = Sequence.ToArray();
                return SerialCharMethod(stepValue, Sequence, serialValue, _arry);
            }

        }

        /// <summary>
        /// 序列号字符查找.
        /// </summary>
        /// <param name="stepValue">步进值.</param>
        /// <param name="Sequence">序列号循环范围.</param>
        /// <param name="serialValue">序列号值.</param>
        /// <param name="chars">字符数组</param>
        /// <returns>newSerial.</returns>
        private string SerialCharMethod(string stepValue, string Sequence, string serialValue, char[] chars)
        {
            var maxV = stepValue.Equals("1") ? chars[chars.Length - 1] : chars[0];
            var minV = stepValue.Equals("1") ? chars[0] : chars[chars.Length - 1];
            var vIntChar = serialValue.Substring(serialValue.Length - 1, 1)[0];
            var vOtherStr = serialValue.Substring(0, serialValue.Length - 1);

            if (maxV == vIntChar)
            {
                vIntChar = minV;
                vOtherStr = SerialMethod(stepValue, Sequence, vOtherStr);
            }
            else
            {
                var cIndex = string.Join("", chars).IndexOf(vIntChar);
                if (cIndex > -1)
                {
                    vIntChar = chars[cIndex + 1];
                }
                else
                {
                    // 其它字符 -> 跳过
                    vOtherStr = SerialMethod(stepValue, Sequence, vOtherStr);
                }
            }

            return vOtherStr + vIntChar;

        }

        #endregion
    }
}
